/**
  Implementacion de la clase que realiza el acceso a la base de datos de la
  cuenta, la base de datos accesada es MySQL y se utiliza el connector para
  C/C++

  Autor: Javier Silva
*/

// Standard C++ includes
#include <stdlib.h>
#include <iostream>
#include <sstream>
#include <stdexcept>

#include <mysql_connection.h>
#include <mysql_driver.h>

#include <cppconn/driver.h>
#include <cppconn/exception.h>
#include <cppconn/resultset.h>
#include <cppconn/statement.h>
#include "CuentaDB.h"
#include "DataBase.h"

using namespace std;

CuentaDB::CuentaDB()
{
}

/**
  Busca una cuenta a partir del No. de cuenta
  Entrada: No de Cuenta a buscar
  Salida: Un objeto de tipo cuenta con todos los datos llenos desde la base de datos, en caso
        de no encontrar la cuenta solicitada, se retorna una cuenta vacia
 */
Cuenta CuentaDB::selectByNoCuenta(int noCuenta){
    sql::Driver * driver = sql::mysql::get_driver_instance();
    /* Usando el Driver se pide una coneccion */
    std::auto_ptr< sql::Connection > con(driver->connect(HOST_URL, USER, PASS));

    /* Se crea un Statement */
    std::auto_ptr< sql::Statement > stmt(con->createStatement());

    //Se señala la base de datos a utilizar
    stringstream sqlDB;
    sqlDB.str("");
    sqlDB << "USE " <<DB_NAME;
    stmt->execute(sqlDB.str());

    //Se crea la consulta
    stringstream sql;
    sql.str("");
    sql << "SELECT * FROM Cuenta WHERE noCuenta ="<< noCuenta <<";";

    //Se crea el Result Set a partir de la consulta deseada
    std::auto_ptr< sql::ResultSet > res(stmt->executeQuery(sql.str()));
    //cout<<"Consulta: "<< "SELECT * FROM Cuenta WHERE noCuenta ="<< noCuenta <<";"<<endl;

    /* Numero de rows en el result set */
    //cout << "#\t\t Rows Count: \t";
    //cout << "res->rowsCount() = " << res->rowsCount() << endl;

    /* Obtener Datos */
    while (res->next()) {
        Cuenta c = Cuenta();
        c.setActiva(res->getBoolean("activa"));
        c.setSaldo(res->getDouble("saldo"));
        c.setNip(res->getInt("nip"));
        c.setNoCuenta(res->getInt("noCuenta"));
        stmt.reset(NULL); /* Limpiar el objeto  */
        con.reset(driver->connect(HOST_URL, USER, PASS));
        return c;
    }
    return Cuenta();
}

/**
  Actualiza el registro COMPLETO en la base de datos
  Entrada: Cuenta a ser actualizada
  Salida: True si la actualización fue correcta, False en otro caso
 */
bool CuentaDB::update(Cuenta cuenta){
    sql::Driver * driver = sql::mysql::get_driver_instance();
    /* Usando el Driver se pide una coneccion */
    std::auto_ptr< sql::Connection > con(driver->connect(HOST_URL, USER, PASS));

    /* Se crea un Statement */
    std::auto_ptr< sql::Statement > stmt(con->createStatement());

    //Se señala la base de datos a utilizar
    stringstream sqlDB;
    sqlDB.str("");
    sqlDB << "USE " <<DB_NAME;
    stmt->execute(sqlDB.str());

    //Se crea la consulta
    stringstream sql;
    sql.str("");
    sql << "UPDATE Cuenta SET nip= "<<cuenta.getNip()<<", saldo="
        <<cuenta.getSaldo()<<", activa="<<cuenta.isActiva()
        <<"  WHERE noCuenta= "<< cuenta.getNoCuenta()<<";";
    int affected_rows = stmt->executeUpdate(sql.str());
    stmt.reset(NULL); /* Limpiar el objeto  */
    con.reset(driver->connect(HOST_URL, USER, PASS));
    //Si se afecto mas de una fila regresar true, de lo contrario regresar false
    return affected_rows > 0? true:false;
}
